(require (planet schematics/schemeunit:3))

;Aplicando T_pq duas vezes:

;a1 = b0.q + a0.q + a0.p
;b1 = b0.p + a0.q

;a2 = b1.q + a1.q + a1.p
;a2 = (b0.p + a0.q).q + (b0.q  + a0.q + a0.p).q + (b0.q  + a0.q + a0.p).p
;a2 = b0.pq + a0.qq + b0.qq + a0.qq + a0.pq + b0.pq + a0.pq + a0.pp
;a2 = b0.(2.pq + qq) + a0(2.pq + qq) + a0.(pp + qq)

;b2 = b1.p + a1.q
;b2 = (b0.p + a0.q).p + (b0.q + a0.q + a0.p).q
;b2 = b0.pp + a0.pq + b0.qq + a0.qq + a0.pq
;b2 = b0.(pp + qq) + a0(2.pq + qq)

;p' = p^2 + q^2
;q' = 2pq + q^2

(define (fib n)
  (fib-iter 1 0 0 1 n))
(define (fib-iter a b p q count)
  (cond ((= count 0) b)
        ((even? count)
         (fib-iter a
                   b
                   (+ (* p p) (* q q))
                   (+ (* 2 p q) (* q q))
                   (/ count 2)))
        (else (fib-iter (+ (* b q) (* a q) (* a p))
                        (+ (* b p) (* a q))
                        p
                        q
                        (- count 1)))))

(check-equal? (fib 0) 0)
(check-equal? (fib 1) 1)
(check-equal? (fib 2) 1)
(check-equal? (fib 3) 2)
(check-equal? (fib 4) 3)
(check-equal? (fib 5) 5)
(check-equal? (fib 6) 8)
(check-equal? (fib 7) 13)
(check-equal? (fib 8) 21)
(check-equal? (fib 9) 34)
